"""
得捷(DigiKey)数字化解决方案主服务

作者：HonestQiao
版本：V1.0
时间：2024-01-22
"""
from flask import Flask
from flask import render_template, request, Response
import threading
import requests
import json
import sys
import time
from datetime import datetime

# 运行模式: True-实际产品 False-沙盒产品
RUN_IN_PRODUCT = False

# 要监控的产品编号
DIGIKEY_PART_NUMBER = "1278-W5500-EVB-PICO-ND"
API_VERSION = 'v4'

# 端口和安全
RUN_IN_PORT = 8888
RUN_IN_SSL = True

if not RUN_IN_PRODUCT:
    client_id = "正式应用的client_id"
    client_secret = "正式应用的client_secret"

    oauth_url = "https://sandbox-api.digikey.com/v1/oauth2/authorize"
    token_url = "https://sandbox-api.digikey.com/v1/oauth2/token"
    api_url_v3 = "https://sandbox-api.digikey.com/Search/v3/Products/{}"
    api_url_v4 = "https://sandbox-api.digikey.com/products/v4/search/{}/productdetails"
else:
    client_id = "沙盒应用的client_id"
    client_secret = "沙盒应用的client_secret"

    oauth_url = "https://api.digikey.com/v1/oauth2/authorize"
    token_url = "https://api.digikey.com/v1/oauth2/token"
    api_url_v3 = "https://api.digikey.com/Search/v3/Products/{}"
    api_url_v4 = "https://api.digikey.com/products/v4/search/{}/productdetails"

# 回调地址
redirect_uri = "https://你的域名/customer/digikey/redirect"
qrcode_url = "https://你的域名/login"

# digikey api token
global access_token_info
# 产品信息
global product_detail
# digikey登录状态
global digikey_login_status
# 是否需要进入登录页
global is_need_login

# 默认未登录digikey
digikey_login_status = False

# 默认为需要进入登录页
is_need_login = True

app = Flask(__name__)

# 首页
@app.route("/", methods=["GET", "POST"])
def home():
    global digikey_login_status,product_detail
    return render_template(
            "home.html",
            isHome=True,
            isLogin=digikey_login_status,
            detail=product_detail
        )

# 登录页
@app.route("/login", methods=["GET", "POST"])
def login():
    global is_need_login
    is_need_login = False
    return render_template(
        "login.html",
        oauth_url=oauth_url,
        redirect_uri=redirect_uri,
        client_id=client_id
    )

# 回调
@app.route("/customer/digikey/redirect", methods=["GET", "POST"])
def digikey_redirect():
    global access_token_info, product_detail, digikey_login_status, is_need_login
    code = request.args.get("code")

    print("收到回调请求")

    if is_need_login:
        print("需要先登录")
        return render_template(
                "home.html",
                isLogin=False,
                detail=product_detail
            )

    print("请求oauth验证")
    header = {"accept": "application/x-www-form-urlencoded"}
    post_data = {
        "client_id": client_id,
        "client_secret": client_secret,
        "code": code,
        "redirect_uri": redirect_uri,
        "grant_type": "authorization_code",
    }
    res = requests.post(token_url, headers=header, data=post_data)
    if res.status_code == 200:
        print("请求oauth验证成功")
        res_dict = res.json()
        # print(res_dict)
        # access_token = res_dict["access_token"]
        access_token_info = res_dict
    else:
        print("请求oauth验证失败")
        res_dict = res.json()
        print(res_dict)
        return render_template(
                "home.html",
                isLogin=False,
                detail=product_detail
            )

    ret = fetch_product_data()
    if ret:
        # return product_detail
        return render_template(
            "home.html",
            isLogin=digikey_login_status,
            detail=product_detail
        )
    else:
        return render_template(
                "home.html",
                isLogin=False,
                detail=product_detail
            )

# api请求
@app.route("/api/v1.0/product/info_json", methods=["GET", "POST"])
def product_detail_json():
    global digikey_login_status, product_detail
    if digikey_login_status:
        product_detail["status"] = 0
        return Response(json.dumps(product_detail), mimetype='application/json')
    else:
        product_detail = {"status":1}
        return Response(json.dumps(product_detail), mimetype='application/json')

# api请求
@app.route("/api/v1.0/product/info", methods=["GET", "POST"])
def product_detail():
    global digikey_login_status, product_detail
    if digikey_login_status:
        # text_head = 'Product Info'
        text_head = '电子元器件价格及库存监视器'
        ret = render_template('product.tpl.json', text_head=text_head, data=product_detail)
        return Response(ret, mimetype='application/json')
    else:
        product_detail = {}
        # text_head = 'Please scan the QR-Code'
        text_head = '电子元器件价格及库存监视器'
        ret = render_template('qrcode.tpl.json', text_head=text_head, qrcode_url=qrcode_url)
        return Response(ret, mimetype='application/json')


# 产品信息数据获取
def fetch_product_data():
    global access_token_info, digikey_login_status, product_detail

    print("请求产品信息")
    api_url = api_url_v4 if API_VERSION == 'v4' else api_url_v3
    request_url = api_url.format(DIGIKEY_PART_NUMBER)
    # request_url = api_url.format(DIGIKEY_PART_NUMBER)+"?requestedQuantity=1"
    access_token = "{} {}".format(access_token_info['token_type'], access_token_info['access_token'])
    headers = {
        "accept": "application/json",
        "Authorization": access_token,
        "X-DIGIKEY-Client-Id": client_id,
        "X-DIGIKEY-Locale-Site": "CN",
        "X-DIGIKEY-Locale-Language": "zhs",
        "X-DIGIKEY-Locale-Currency": "CNY",
    }
    # print(headers)

    res = requests.get(request_url, headers=headers)
    if res.status_code == 200:
        print("请求产品信息成功")
        prod_info = res.json()
        # print(prod_info)
        digikey_login_status = True

        if API_VERSION == 'v4':
            prod_info = prod_info.get('Product', {})
            # 名称：{{detail.ManufacturerProductNumber}}
            # 编号：{{detail.ProductVariations.DigiKeyProductNumber}}
            # 简介：{{detail.Description.ProductDescription}}
            # 详介：{{detail.Description.DetailedDescription}}
            # 价格：{{detail.UnitPrice}}
            # 库存：{{detail.QuantityAvailable}}
            # 状态：{{detail.ProductStatus.Status}}
            product_detail = {
                "name": prod_info['ManufacturerProductNumber'],
                "pid": prod_info['ProductVariations'][0]['DigiKeyProductNumber'],
                "desc": prod_info['Description']['ProductDescription'],
                "detail": prod_info['Description']['DetailedDescription'],
                "price": prod_info['UnitPrice'],
                "quantity": prod_info['QuantityAvailable'],
                "status": prod_info['ProductStatus']['Status'],
                "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
        else:
            prod_info = prod_info if prod_info else {}
            # 名称：{{detail.ManufacturerPartNumber}}
            # 编号：{{detail.DigiKeyPartNumber}}
            # 简介：{{detail.ProductDescription}}
            # 详介：{{detail.DetailedDescription}}
            # 价格：{{detail.StandardPricing[0].UnitPrice}}
            # 库存：{{detail.QuantityAvailable}}
            # 状态：{{detail.ProductStatus}}
            product_detail = {
                "name": prod_info['ManufacturerPartNumber'],
                "pid": prod_info['DigiKeyPartNumber'],
                "desc": prod_info['ProductDescription'],
                "detail": prod_info['DetailedDescription'],
                "price": prod_info['StandardPricing'][0]['UnitPrice'],
                "quantity": prod_info['QuantityAvailable'],
                "status": prod_info['ProductStatus'],
                "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
        return True
    else:
        digikey_login_status = False
        print("请求产品信息失败")
        res_dict = res.json()
        print(res_dict)
        return False

# 定时数据刷新
# @gen.coroutine
def refresh_data():
    global access_token_info, digikey_login_status, product_detail
    try:
        print("数据更新服务启动")
        while True:
            if digikey_login_status:
                time.sleep(30)
                print("刷新数据开始")

                ret = fetch_product_data()
                if ret:
                    print("刷新数据成功")
                else:
                    print("刷新数据失败")
            else:
                time.sleep(1)

    except Exception:
        pass

if __name__ == "__main__":
    print("启动数据更新服务")
    thread = threading.Thread(target=refresh_data)
    thread.start()

    if RUN_IN_SSL:
        app.run(
            debug=True, host="0.0.0.0", port=RUN_IN_PORT, ssl_context=("server.crt", "server.key")
        )
    else:
        app.run(
            debug=True, host="0.0.0.0", port=RUN_IN_PORT
        )
